import 'dart:convert';
import 'dart:io';

import 'package:flutter/widgets.dart';
import 'package:crypto/crypto.dart';
import 'package:get/get.dart';
import 'package:native_dart_package/http/request/exception/api_exception.dart';
import 'package:native_dart_package/loading/loading_util.dart';
import 'package:xbr_gaode_search/core/lat_lng.dart';
import 'package:xbr_gaode_search/xbr_gaode_search.dart';
import 'package:yt_devops/model/amap_poi.dart';
import 'package:yt_devops/pages/amap/map_const_config.dart';
import 'package:yt_devops/resources/str_res_keys.dart';
import 'package:yt_devops/utils/enums.dart';
import 'package:yt_devops/utils/func_utils.dart';

class MapServices {
  static HttpClient httpClient = HttpClient();

  static Future<AmapPoi?> geoGoogleLatng(
      BuildContext context, LatLngModel latLng) async {
    AmapPoi? poi;
    var request = await httpClient.getUrl(Uri.tryParse(
        'https://maps.googleapis.com/maps/api/geocode/json?language=${Get.locale?.languageCode}&latlng=${latLng.latitude},${latLng.longitude}&key=${MapConstConfig.googleApiKey}')!);

    final response = await request.close();

    try {
      if (response.statusCode == 200) {
        String responseBody = await response.transform(utf8.decoder).join();
        var data = json.decode(responseBody);
        if (data?['results']?.isNotEmpty == true) {
          poi = AmapPoi(
              latitude: latLng.latitude,
              longitude: latLng.longitude,
              formattedAddress: data['results'][0]['formatted_address']);
        }
      }
    } catch (e) {
      FuncUtils.requestTipsDislog(
          context, ResKey.addressResolutionFailed.tr, false);
    }
    return poi;
  }

  static Future<AmapPoi?> geoAmapLatng(
      BuildContext context, LatLngModel latLng) async {
    String? tip;

    var params =
        "key=${MapConstConfig.amapWebApiKey}&location=${latLng.longitude},${latLng.latitude}";

    var url =
        "https://restapi.amap.com/v3/geocode/regeo?$params&sig=${sig(params)}";

    var request = await httpClient.getUrl(Uri.tryParse(url)!);
    final response = await request.close();

    if (response.statusCode == 200) {
      String responseBody = await response.transform(utf8.decoder).join();
      var data = json.decode(responseBody);

      if (data['status'] == '1') {
        var regeocodeAddress = data['regeocode'];
        var address = regeocodeAddress['addressComponent'];

        return AmapPoi(
          latitude: latLng.latitude,
          longitude: latLng.longitude,
          formattedAddress: regeocodeAddress['formatted_address'],
          adcode: address['adcode'],
        );
      } else {
        tip = data['info'];
      }
    }

    FuncUtils.requestTipsDislog(
      context,
      tip ?? ResKey.addressResolutionFailed.tr,
      false,
    );
  }

  static Future<AmapPoi?> geopLatng(
      {required BuildContext context,
      required MapType type,
      required LatLngModel latLng}) async {
    if (type == MapType.amap) {
      return await geoAmapLatng(context, latLng);
    } else {
      return await geoGoogleLatng(context, latLng);
    }
  }

  static Future<List<AmapPoi>?> searchAmpPoi(
      LatLngModel position, String text) async {
    List<AmapPoi> poiList = [];
    String? errorTip;

    var param =
        "key=${MapConstConfig.amapWebApiKey}&keywords=$text&location=${position.latitude},${position.longitude}";

    var url =
        "https://restapi.amap.com/v3/assistant/inputtips?${param}&sig=${sig(param)}";

    var request = await httpClient.getUrl(Uri.tryParse(url)!);
    final response = await request.close();

    if (response.statusCode == 200) {
      String responseBody = await response.transform(utf8.decoder).join();
      var data = json.decode(responseBody);

      if (data['status'] == "1") {
        var list = data['tips'];
        poiList = list
            .map<AmapPoi>(
              (item) => AmapPoi(
                  name: item['name'],
                  latitude: double.parse(item['location'].split(',')[1]),
                  longitude: double.parse(item['location'].split(',')[0]),
                  formattedAddress: item['address'],
                  adcode: item['adcode'],
                  district: item['district']),
            )
            .toList();
        return poiList;
      } else {
        errorTip = data['info'];
      }
    }
    throw ApiException(-1, errorTip);
  }

  static String sig(String data) {
    var content =
        const Utf8Encoder().convert('$data${MapConstConfig.amapWebSignCode}');
    var digest = md5.convert(content);
    return digest.toString();
  }
}
